﻿using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;

namespace bcpJson
{
	class Program
	{
		static void Main(string[] args)
		{
			Stopwatch sw = new Stopwatch();
			sw.Start();

			var setting = new ExportSetting();
			if (CommandLine.Parser.Default.ParseArguments(args, setting) && setting.Valid())
			{
				var result = Generate(setting);
				sw.Stop();
				Console.ForegroundColor = ConsoleColor.Green;
				Console.WriteLine("Exported {0}\tRows in {1}", result, sw.Elapsed);
			}
			else
			{
				Console.ForegroundColor = ConsoleColor.Yellow;
				Console.WriteLine(setting.GetUsage());
			}

			Console.ResetColor();
		}

		private static long Generate(ExportSetting setting)
		{
			var count = 0L;

			using (var conn = new SqlConnection(setting.GetConnectionString()))
			{
				using (var cmd = new SqlCommand("select name from sys.tables", conn))
				{
					conn.Open();
					var tables = new Dictionary<string, string>();
					string dir;

					if (setting.MultiExport.HasValue)
					{
						if (setting.MultiExport.Value)
						{
							dir = setting.Path;

							using(var reader = cmd.ExecuteReader(CommandBehavior.SingleResult))
							{
								while (reader.Read())
								{
									var table = reader.GetString(0);
									tables.Add(string.Format("[{0}]", table), Path.Combine(setting.Path, table) + ".json");
								}
							}
						}
						else
						{
							dir = Path.GetDirectoryName(setting.Path);
							tables.Add(string.Format("({0})", setting.Query), setting.Path);
						}
					}
					else
					{
						throw new ArgumentNullException();
					}

					if (tables.Count > 0)
					{
						try
						{
							if (!Directory.Exists(dir))
							{
								Directory.CreateDirectory(dir);
							}							
						}
						catch (Exception)
						{							
							throw;
						}

						tables.ToList().ForEach(t => {
							cmd.CommandText = string.Format("SELECT * FROM {0} t", t.Key);
							var result = CollectionGenerate(cmd, t.Value);
							count += result;
							Console.WriteLine("Exported {0}\tRows of [{1}]", result, t.Key);
						});

						/*
						if (setting.ImportScript)
						{
							using (var writer = new StreamWriter(Path.Combine(dir, "import.bat")))
							{
								tables.ToList().ForEach(t => writer.WriteLine("xxxxxx {0}", t.Value));
							}
						}
						 */
					}
				}
			}

			return count;
		}

		private static long CollectionGenerate(SqlCommand cmd, string path)
		{
			var rowCount = 0L;

			using (var reader = cmd.ExecuteReader(CommandBehavior.SingleResult))
			{
				var fieldFields = Enumerable.Range(0, reader.FieldCount).Select(d => new { Index = d, Name = reader.GetName(d)/*, Type = reader.GetFieldType(d)*/ }).ToList();

				using (var jsonWriter = new JsonTextWriter(new StreamWriter(path, false)))
				{
					while (reader.Read())
					{
						jsonWriter.WriteStartObject();

						fieldFields.ForEach(d =>
						{
							jsonWriter.WritePropertyName(d.Name);
							jsonWriter.WriteValue(reader.GetValue(d.Index));
						});

						jsonWriter.WriteEndObject();
						jsonWriter.WriteWhitespace(Environment.NewLine);

						rowCount++;
					}
				}
			}

			return rowCount;
		}
	}
}
